/**
 * 给定若干个页面请求，使用LRU缓存策略
 * for i in [0, m]:
 *   回答问题：假设给定i个缓存，缓存不命中的次数
 * 假设第i个请求与第j个请求请求的是同一个页面，
 * 则j请求是否缓存命中或者不命中的关键在于i、j之间的不同页面的数量（称为"间隔数"）
 * 与缓存空间的大小关系。
 * 当 间隔数 >= 缓存空间 时，就会增加一次缓存不命中。
 * 因此只需要输出所有间隔数的数量即可，然后累加即可。
 * 数间隔数比较简单，是树状数组的典型应用。
 * 即给定数组A，求相等相邻的两个位置之间不同种类数的数量
 * 弄一个树状数组B
 * for i, v in A:
 *     求和B[prev[v], i]，即相邻两个v之间的间隔数
 *     将B[prev[v]]减1
 *     将B[i]加1
 *     prev[v] = i
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;


using llt = long long;
using Real = double;
using vi = vector<int>;
using pii = pair<int, int>;

struct FenwickTree{ // 树状数组

using value_type = long long int;
using vec_type = vector<value_type>;

int n;
vec_type c;

FenwickTree() = default;

static int lowbit(int x){return x & -x;}

void init(int nn){this->c.assign((this->n=nn) + 1, 0);}

void modify(int pos, value_type delta){
    for(int i=pos;i<=this->n;i+=lowbit(i)) this->c[i] += delta;
}

value_type query(int pos)const{
    value_type ans = 0;
    for(int i=pos;i;i-=lowbit(i)) ans += this->c[i];
    return ans;
}

value_type query(int s, int e)const{return this->query(e) - this->query(s - 1);}

}Bt;


int M;
vi A;
vi Ans;

void proc(){    
    Bt.init(M);
    map<int, int> cnt;
    vi pre(1000000 + 1, 0);
    for(int p,v,i=0;i<M;++i){
        p = i + 1;
        v = A[i];
        if(pre[v]){
            Bt.modify(pre[v], -1);
            cnt[Bt.query(pre[v], p)] += 1;
        }else{
            cnt[M] += 1;
        }        
        Bt.modify(pre[v] = p, 1);
    }

    Ans.assign(M + 1, 0);
    int sum = 0;

    int another = M;
    for(auto it=cnt.rbegin(),jt=++cnt.rbegin(),et=cnt.rend();jt!=et;++it,++jt){
        int last = it->first;
        int start = jt->first;
        sum += it->second;
        fill(Ans.begin() + start + 1, Ans.begin() + last + 1, sum);
    }

    cout << (Ans[0] = M);
    for(int i=1;i<=M;++i) cout << " " << Ans[i];
    cout << endl;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    cin >> M;
    A.assign(M, {});
    for(auto & i : A) cin >> i;
    proc();
    return 0;
}